// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
-const { Gio, St } = imports.gi;
+const { Gio, GObject, St } = imports.gi;
const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main;
}
};
-var AutorunSource = class extends MessageTray.Source {
- constructor(manager, mount, apps) {
- super(mount.get_name());
+var AutorunSource = GObject.registerClass(
+class AutorunSource extends MessageTray.Source {
+ _init(manager, mount, apps) {
+ super._init(mount.get_name());
this._manager = manager;
this.mount = mount;
// add ourselves as a source, and popup the notification
Main.messageTray.add(this);
- this.notify(this._notification);
+ this.showNotification(this._notification);
}
getIcon() {
_createPolicy() {
return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
}
-};
+});
-var AutorunNotification = class extends MessageTray.Notification {
- constructor(manager, source) {
- super(source, source.title);
+var AutorunNotification = GObject.registerClass(
+class AutorunNotification extends MessageTray.Notification {
+ _init(manager, source) {
+ super._init(source, source.title);
this._manager = manager;
this._mount = source.mount;
let app = Gio.app_info_get_default_for_type('inode/directory', false);
startAppForMount(app, this._mount);
}
-};
+});
var Component = AutorunManager;
});
Main.messageTray.add(source);
- source.notify(notification);
+ source.showNotification(notification);
}
_newRequest(agent, requestId, connection, settingName, hints, flags) {
// We are already handling the channel, display the source
let source = this._chatSources[channel.get_object_path()];
if (source)
- source.notify();
+ source.showNotification();
}
}
}
}
}) : null;
-var ChatSource = class extends MessageTray.Source {
- constructor(account, conn, channel, contact, client) {
- super(contact.get_alias());
+var ChatSource = HAVE_TP ? GObject.registerClass(
+class ChatSource extends MessageTray.Source {
+ _init(account, conn, channel, contact, client) {
+ super._init(contact.get_alias());
this._account = account;
this._contact = contact;
this._notification.appendMessage(pendingMessages[i], true);
if (pendingMessages.length > 0)
- this.notify();
+ this.showNotification();
}
destroy(reason) {
_notifyTimeout() {
if (this._pendingMessages.length != 0)
- this.notify();
+ this.showNotification();
this._notifyTimeoutId = 0;
this._notification.appendMessage(message);
}
- notify() {
- super.notify(this._notification);
+ showNotification() {
+ super.showNotification(this._notification);
}
respond(text) {
// 'pending-message-removed' for each one.
this._channel.ack_all_pending_messages_async(null);
}
-};
+}) : null;
-var ChatNotification = class extends MessageTray.Notification {
- constructor(source) {
- super(source, source.title, null,
- { secondaryGIcon: source.getSecondaryIcon() });
+var ChatNotification = HAVE_TP ? GObject.registerClass({
+ Signals: {
+ 'message-removed': { param_types: [Tp.Message.$gtype] },
+ 'message-added': { param_types: [Tp.Message.$gtype] },
+ 'timestamp-changed': { param_types: [Tp.Message.$gtype] },
+ }
+}, class ChatNotification extends MessageTray.Notification {
+ _init(source) {
+ super._init(source, source.title, null,
+ { secondaryGIcon: source.getSecondaryIcon() });
this.setUrgency(MessageTray.Urgency.HIGH);
this.setResident(true);
this._filterMessages();
}
-};
+}) : null;
var ChatLineBox = GObject.registerClass(
class ChatLineBox extends St.BoxLayout {
}
_onSourceAdded(tray, source) {
- source.connect('count-updated', this._updateCount.bind(this));
+ source.connect('notify::count', this._updateCount.bind(this));
this._sources.push(source);
this._updateCount();
}
messageTray.add(source);
let notification = new MessageTray.Notification(source, msg, details);
notification.setTransient(true);
- source.notify(notification);
+ source.showNotification(notification);
}
/**
// source, such as whether to play sound or honour the critical bit.
//
// A notification without a policy object will inherit the default one.
-var NotificationPolicy = class NotificationPolicy {
- constructor(params) {
- params = Params.parse(params, {
- enable: true,
- enableSound: true,
- showBanners: true,
- forceExpanded: false,
- showInLockScreen: true,
- detailsInLockScreen: false,
- });
- Object.getOwnPropertyNames(params).forEach(key => {
- let desc = Object.getOwnPropertyDescriptor(params, key);
- Object.defineProperty(this, `_${key}`, desc);
- });
- }
-
+var NotificationPolicy = GObject.registerClass({
+ GTypeName: 'MessageTray_NotificationPolicy',
+ Properties: {
+ 'enable': GObject.ParamSpec.boolean(
+ 'enable', 'enable', 'enable',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
+ true),
+ 'enable-sound': GObject.ParamSpec.boolean(
+ 'enable-sound', 'enable-sound', 'enable-sound',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
+ true),
+ 'show-banners': GObject.ParamSpec.boolean(
+ 'show-banners', 'show-banners', 'show-banners',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
+ true),
+ 'force-expanded': GObject.ParamSpec.boolean(
+ 'force-expanded', 'force-expanded', 'force-expanded',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
+ false),
+ 'show-in-lock-screen': GObject.ParamSpec.boolean(
+ 'show-in-lock-screen', 'show-in-lock-screen', 'show-in-lock-screen',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
+ false),
+ 'details-in-lock-screen': GObject.ParamSpec.boolean(
+ 'details-in-lock-screen', 'details-in-lock-screen', 'details-in-lock-screen',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
+ false),
+ }
+}, class NotificationPolicy extends GObject.Object {
// Do nothing for the default policy. These methods are only useful for the
// GSettings policy.
store() { }
- destroy() { }
-
- get enable() {
- return this._enable;
+ destroy() {
+ this.run_dispose();
}
get enableSound() {
- return this._enableSound;
+ return this.enable_sound;
}
get showBanners() {
- return this._showBanners;
+ return this.show_banners;
}
get forceExpanded() {
- return this._forceExpanded;
+ return this.force_expanded;
}
get showInLockScreen() {
- return this._showInLockScreen;
+ return this.show_in_lock_screen;
}
get detailsInLockScreen() {
- return this._detailsInLockScreen;
+ return this.details_in_lock_screen;
}
-};
-Signals.addSignalMethods(NotificationPolicy.prototype);
+});
-var NotificationGenericPolicy =
-class NotificationGenericPolicy extends NotificationPolicy {
- constructor() {
- super();
+var NotificationGenericPolicy = GObject.registerClass({
+ GTypeName: 'MessageTray_NotificationGenericPolicy'
+}, class NotificationGenericPolicy extends NotificationPolicy {
+ _init() {
+ super._init();
this.id = 'generic';
this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' });
this._masterSettings.connect('changed', this._changed.bind(this));
}
- store() { }
-
destroy() {
this._masterSettings.run_dispose();
+
+ super.destroy();
}
_changed(settings, key) {
- this.emit('policy-changed', key);
+ if (this.constructor.find_property(key))
+ this.notify(key);
}
get showBanners() {
get showInLockScreen() {
return this._masterSettings.get_boolean('show-in-lock-screen');
}
-};
+});
-var NotificationApplicationPolicy =
-class NotificationApplicationPolicy extends NotificationPolicy {
- constructor(id) {
- super();
+var NotificationApplicationPolicy = GObject.registerClass({
+ GTypeName: 'MessageTray_NotificationApplicationPolicy'
+}, class NotificationApplicationPolicy extends NotificationPolicy {
+ _init(id) {
+ super._init();
this.id = id;
this._canonicalId = this._canonicalizeId(id);
destroy() {
this._masterSettings.run_dispose();
this._settings.run_dispose();
+
+ super.destroy();
}
_changed(settings, key) {
- this.emit('policy-changed', key);
- if (key == 'enable')
- this.emit('enable-changed');
+ if (this.constructor.find_property(key))
+ this.notify(key);
}
_canonicalizeId(id) {
get detailsInLockScreen() {
return this._settings.get_boolean('details-in-lock-screen');
}
-};
+});
// Notification:
// @source: the notification's Source
// @source allows playing sounds).
//
// [1] https://developer.gnome.org/notification-spec/#markup
-var Notification = class Notification {
- constructor(source, title, banner, params) {
+var Notification = GObject.registerClass({
+ GTypeName: 'MessageTray_Notification',
+ Properties: {
+ 'acknowledged': GObject.ParamSpec.boolean(
+ 'acknowledged', 'acknowledged', 'acknowledged',
+ GObject.ParamFlags.READWRITE,
+ false),
+ },
+ Signals: {
+ 'activated': {},
+ 'destroy': { param_types: [GObject.TYPE_UINT] },
+ 'updated': { param_types: [GObject.TYPE_BOOLEAN] },
+ }
+}, class Notification extends GObject.Object {
+ _init(source, title, banner, params) {
+ super._init();
+
this.source = source;
this.title = title;
this.urgency = Urgency.NORMAL;
if (this._acknowledged == v)
return;
this._acknowledged = v;
- this.emit('acknowledged-changed');
+ this.notify('acknowledged');
}
setUrgency(urgency) {
destroy(reason = NotificationDestroyedReason.DISMISSED) {
this.emit('destroy', reason);
}
-};
-Signals.addSignalMethods(Notification.prototype);
+});
var NotificationBanner =
class NotificationBanner extends Calendar.NotificationMessage {
this.add_actor(this._counterBin);
- this._countUpdatedId = this._source.connect('count-updated', this._updateCount.bind(this));
+ this._countUpdatedId = this._source.connect('notify::count', this._updateCount.bind(this));
this._updateCount();
this.connect('destroy', () => {
}
});
-var Source = class Source {
- constructor(title, iconName) {
+var Source = GObject.registerClass({
+ GTypeName: 'MessageTray_Source',
+ Properties: {
+ 'count': GObject.ParamSpec.int(
+ 'count', 'count', 'count',
+ GObject.ParamFlags.READABLE,
+ 0, GLib.MAXINT32, 0),
+ 'policy': GObject.ParamSpec.object(
+ 'policy', 'policy', 'policy',
+ GObject.ParamFlags.READWRITE,
+ NotificationPolicy.$gtype),
+ 'title': GObject.ParamSpec.string(
+ 'title', 'title', 'title',
+ GObject.ParamFlags.READWRITE,
+ null),
+ },
+ Signals: {
+ 'destroy': { param_types: [GObject.TYPE_UINT] },
+ 'icon-updated': {},
+ 'notification-added': { param_types: [Notification.$gtype] },
+ 'notification-show': { param_types: [Notification.$gtype] },
+ }
+}, class Source extends GObject.Object {
+ _init(title, iconName) {
+ super._init({ title: title });
+
this.SOURCE_ICON_SIZE = 48;
- this.title = title;
this.iconName = iconName;
this.isChat = false;
}
countUpdated() {
- this.emit('count-updated');
+ super.notify('count');
}
_createPolicy() {
}
setTitle(newTitle) {
+ if (this.title == newTitle)
+ return;
+
this.title = newTitle;
- this.emit('title-changed');
+ this.notify('title');
}
createBanner(notification) {
this.notifications.shift().destroy(NotificationDestroyedReason.EXPIRED);
notification.connect('destroy', this._onNotificationDestroy.bind(this));
- notification.connect('acknowledged-changed', this.countUpdated.bind(this));
+ notification.connect('notify::acknowledged', this.countUpdated.bind(this));
this.notifications.push(notification);
this.emit('notification-added', notification);
this.countUpdated();
}
- notify(notification) {
+ showNotification(notification) {
notification.acknowledged = false;
this.pushNotification(notification);
if (this.policy.showBanners || notification.urgency == Urgency.CRITICAL) {
- this.emit('notify', notification);
+ this.emit('notification-show', notification);
} else {
notification.playSound();
}
}
+ notify(propName) {
+ if (propName instanceof Notification) {
+ try {
+ throw new Error('Source.notify() has been moved to Source.showNotification()' +
+ 'this code will break in the future');
+ } catch (e) {
+ logError(e);
+ this.showNotification(propName);
+ return;
+ }
+ }
+
+ super.notify(propName);
+ }
+
destroy(reason) {
this.policy.destroy();
this.countUpdated();
}
-};
-Signals.addSignalMethods(Source.prototype);
+});
var MessageTray = class MessageTray {
constructor() {
// Register that we got a notification for this source
source.policy.store();
- source.policy.connect('enable-changed', () => {
+ source.policy.connect('notify::enable', () => {
this._onSourceEnableChanged(source.policy, source);
});
- source.policy.connect('policy-changed', this._updateState.bind(this));
+ source.policy.connect('notify', this._updateState.bind(this));
this._onSourceEnableChanged(source.policy, source);
}
_addSource(source) {
let obj = {
- notifyId: 0,
+ showId: 0,
destroyId: 0,
};
this._sources.set(source, obj);
- obj.notifyId = source.connect('notify', this._onNotify.bind(this));
+ obj.showId = source.connect('notification-show', this._onNotificationShow.bind(this));
obj.destroyId = source.connect('destroy', this._onSourceDestroy.bind(this));
this.emit('source-added', source);
let obj = this._sources.get(source);
this._sources.delete(source);
- source.disconnect(obj.notifyId);
+ source.disconnect(obj.showId);
source.disconnect(obj.destroyId);
this.emit('source-removed', source);
}
}
- _onNotify(source, notification) {
+ _onNotificationShow(_source, notification) {
if (this._notification == notification) {
// If a notification that is being shown is updated, we update
// how it is shown and extend the time until it auto-hides.
};
Signals.addSignalMethods(MessageTray.prototype);
-var SystemNotificationSource = class SystemNotificationSource extends Source {
- constructor() {
- super(_("System Information"), 'dialog-information-symbolic');
+var SystemNotificationSource = GObject.registerClass(
+class SystemNotificationSource extends Source {
+ _init() {
+ super._init(_("System Information"), 'dialog-information-symbolic');
}
open() {
this.destroy();
}
-};
+});
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */
-const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
+const { GdkPixbuf, Gio, GLib, GObject, Shell, St } = imports.gi;
const Config = imports.misc.config;
const Main = imports.ui.main;
}
};
-var FdoNotificationDaemonSource =
+var FdoNotificationDaemonSource = GObject.registerClass(
class FdoNotificationDaemonSource extends MessageTray.Source {
- constructor(title, pid, sender, appId) {
- super(title);
+ _init(title, pid, sender, appId) {
+ super._init(title);
this.pid = pid;
this.app = this._getApp(appId);
if (notification.resident && this.app && tracker.focus_app == this.app)
this.pushNotification(notification);
else
- this.notify(notification);
+ this.showNotification(notification);
}
_getApp(appId) {
return null;
}
}
-};
+});
const PRIORITY_URGENCY_MAP = {
low: MessageTray.Urgency.LOW,
urgent: MessageTray.Urgency.CRITICAL
};
-var GtkNotificationDaemonNotification =
+var GtkNotificationDaemonNotification = GObject.registerClass(
class GtkNotificationDaemonNotification extends MessageTray.Notification {
- constructor(source, notification) {
- super(source);
+ _init(source, notification) {
+ super._init(source);
this._serialized = GLib.Variant.new('a{sv}', notification);
let { title,
serialize() {
return this._serialized;
}
-};
+});
const FdoApplicationIface = loadInterfaceXML('org.freedesktop.Application');
const FdoApplicationProxy = Gio.DBusProxy.makeProxyWrapper(FdoApplicationIface);
function InvalidAppError() {}
-var GtkNotificationDaemonAppSource =
+var GtkNotificationDaemonAppSource = GObject.registerClass(
class GtkNotificationDaemonAppSource extends MessageTray.Source {
- constructor(appId) {
+ _init(appId) {
let objectPath = objectPathFromAppId(appId);
if (!GLib.Variant.is_object_path(objectPath))
throw new InvalidAppError();
if (!app)
throw new InvalidAppError();
- super(app.get_name());
+ super._init(app.get_name());
this._appId = appId;
this._app = app;
this._notifications[notificationId] = notification;
if (showBanner)
- this.notify(notification);
+ this.showNotification(notification);
else
this.pushNotification(notification);
}
return [this._appId, notifications];
}
-};
+});
const GtkNotificationsIface = loadInterfaceXML('org.gtk.Notifications');
delete this._sources[appId];
this._saveNotifications();
});
- source.connect('count-updated', this._saveNotifications.bind(this));
+ source.connect('notify::count', this._saveNotifications.bind(this));
Main.messageTray.add(source);
this._sources[appId] = source;
return source;
if (undoCallback)
notification.addAction(_("Undo"), this._onUndoClicked.bind(this));
- this._source.notify(notification);
+ this._source.showNotification(notification);
}
};
this._showSource(source, obj, obj.sourceBox);
this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
- obj.sourceCountChangedId = source.connect('count-updated', source => {
+ obj.sourceCountChangedId = source.connect('notify::count', source => {
this._countChanged(source, obj);
});
- obj.sourceTitleChangedId = source.connect('title-changed', source => {
+ obj.sourceTitleChangedId = source.connect('notify::title', source => {
this._titleChanged(source, obj);
});
- obj.policyChangedId = source.policy.connect('policy-changed', (policy, key) => {
- if (key == 'show-in-lock-screen')
+ obj.policyChangedId = source.policy.connect('notify', (policy, pspec) => {
+ if (pspec.name == 'show-in-lock-screen')
this._visibleChanged(source, obj);
else
this._detailedChanged(source, obj);
}
};
-var ShellUnmountNotifier = class extends MessageTray.Source {
- constructor() {
- super('', 'media-removable');
+var ShellUnmountNotifier = GObject.registerClass(
+class ShellUnmountNotifier extends MessageTray.Source {
+ _init() {
+ super._init('', 'media-removable');
this._notification = null;
Main.messageTray.add(this);
this._notification.update(header, text);
}
- this.notify(this._notification);
+ this.showNotification(this._notification);
}
done(message) {
let notification = new MessageTray.Notification(this, message, null);
notification.setTransient(true);
- this.notify(notification);
+ this.showNotification(notification);
}
}
-};
+});
var ShellMountQuestionDialog = GObject.registerClass({
Signals: { 'response': { param_types: [GObject.TYPE_INT] } }
this._notification.connect('destroy', () => {
this._notification = null;
});
- this._source.notify(this._notification);
+ this._source.showNotification(this._notification);
}
_onActivationFailed(_device, _reason) {
if (app)
app.activate();
});
- this._source.notify(this._notification);
+ this._source.showNotification(this._notification);
}
/* Session callbacks */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WindowAttentionHandler */
-const Shell = imports.gi.Shell;
+const { GObject, Shell } = imports.gi;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
return;
let app = this._tracker.get_window_app(window);
- let source = new Source(app, window);
+ let source = new WindowAttentionSource(app, window);
Main.messageTray.add(source);
let [title, banner] = this._getTitleAndBanner(app, window);
});
notification.setForFeedback(true);
- source.notify(notification);
+ source.showNotification(notification);
source.signalIDs.push(window.connect('notify::title', () => {
let [title, banner] = this._getTitleAndBanner(app, window);
}
};
-var Source = class WindowAttentionSource extends MessageTray.Source {
- constructor(app, window) {
- super(app.get_name());
+var WindowAttentionSource = GObject.registerClass(
+class WindowAttentionSource extends MessageTray.Source {
+ _init(app, window) {
+ super._init(app.get_name());
this._window = window;
this._app = app;
open() {
Main.activateWindow(this._window);
}
-};
+});